#ifndef __VANILA_NATIVE_HH__
#define __VANILA_NATIVE_HH__

#include "vanila/value.h"
#include <vector>
#include <cstdint>
#include <string>

#define REGISTER_NATIVE(functionName)\
static Value functionName(uint32_t argCount, Value* args)

namespace vanila
{
class VirtualMachine;
class Allocator;

class Native
{
public:
    class System
    {    
    public:
        //! \brief get current tick(s)
        REGISTER_NATIVE(clock);
        
        //! \brief exit the interpter
        REGISTER_NATIVE(exit);

        //! \brief control satck show
        REGISTER_NATIVE(showStack);
        REGISTER_NATIVE(showBytecodes);

        //! \brief print 
        REGISTER_NATIVE(print);
        REGISTER_NATIVE(hash);
    };

public:
    class DataStructure
    {
    public:
        //! \brief list operation
        REGISTER_NATIVE(listInit);
        REGISTER_NATIVE(listAppend);
        REGISTER_NATIVE(listInsert);
        REGISTER_NATIVE(listPop);

        //! \brief dictionary operation
        REGISTER_NATIVE(dictInit);
        REGISTER_NATIVE(dictAdd);
        REGISTER_NATIVE(dictGet);

        //! \brief set operation
        REGISTER_NATIVE(setInit);
        REGISTER_NATIVE(setAdd);
        REGISTER_NATIVE(setContain);
    };

private:
    static VirtualMachine* vm;
    static Allocator* allocator;

    //! \brief check native function's arguments count
    static void assertArgumentCount(uint32_t argCount, uint32_t targetCount, const char* name);
};
}

#undef REGISTER_NATIVE

#endif